package mini.expr;
import java.util.List;
import java.util.LinkedList;

import mini.ExpressionList;
import mini.Env;
import mini.Proc;
import mini.oo.MiniClassDefinition;
import mini.oo.MiniClassInstantiation;
import mini.util.MiniUtil;


//added for 2c
public class FCOrClassInstan extends Expr {

    private String funcid = null;	// If it's a symbolic reference
    private ExpressionList explist;
    private Proc proc = null;	// If it's a literal reference

    public FCOrClassInstan(String id, ExpressionList el) {
        funcid = id;
        explist = el;
    }

    public FCOrClassInstan(Proc proc, ExpressionList el) {
        this.proc = proc;
        funcid = "lambda";
        explist = el;
    }

    public Element eval(List<Env> listOfEnvs, LinkedList var) {

    	// Assume we've set the proc literally
    	Proc procToCall = proc;
    	
    	// But if might be a function that we defined
    	if( procToCall == null ) {
        	// It might be the name of a function itself
        	procToCall = MiniUtil.lookupFunction(listOfEnvs,funcid);
    	}
    	
    	// Or, it could be an element that points to a function
    	if( procToCall == null ) {
    		Element elem = MiniUtil.lookupSymbol(listOfEnvs, funcid);
    		if( elem != null ) {
        		procToCall = elem.getProcValue();
    		}
    	}
    	
    	// Or maybe it's a class instantiation
    	MiniClassDefinition classDef = null;
    	if( procToCall == null ) {
    		classDef = MiniUtil.lookupClass(listOfEnvs, funcid);
    	}
    	
    	// Okay, did we find a process?
    	Element elem = null;
    	if( procToCall != null ) {
        	elem = procToCall.apply(listOfEnvs, var, explist);
    	} else if( classDef != null ) {
    		elem = new Element(new MiniClassInstantiation(listOfEnvs,var,classDef,explist));
    	} else {
    		System.err.println( "Error: Could not figure out the function call! Badness will happen." );
    	}
    	
    	return elem;
    }
}